﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics.Joints;

namespace CaptialVices
{
    public class Player : ICustomDrawable
    {
        private DrawablePhysicsObject torso;
        private DrawablePhysicsObject wheel;
        private RevoluteJoint axis;

        private DateTime previousJump;                  // time at which we previously jumped
        private const float jumpInterval = 1.0f;        // in seconds
        private Vector2 jumpForce = new Vector2(0, -1); // applied force when jumping
        private const float speed = 3.0f;               // wheel rotations per second when moving
        private AnimatedSprite sprite;

        public Vector2 LinearSpeed
        {
            get { return wheel.Body.LinearVelocity; }
            private set { }
        }

        /// <summary>
        /// Creates a controlable player
        /// </summary>        
        public Player(World world, AnimatedSprite sprite, Texture2D torsoTexture, Texture2D wheelTexture, Vector2 size, float mass, Vector2 startPosition)
        {
            this.sprite = sprite;
            // Because the player is a composition of two bodies we first need
            // to calculate the sizes of the individual bodies
            Vector2 torsoSize = new Vector2(size.X, size.Y - size.X / 2.0f);
            float wheelSize = size.X;

            // Create the torso which
            torso = new DrawablePhysicsObject(world, new AnimatedSprite(torsoTexture), torsoSize, mass / 2.0f);
            torso.Position = startPosition;

            // Create the feet of the body, here implemented as high friction wheels 
            wheel = new DrawablePhysicsObject(world, new AnimatedSprite(wheelTexture), wheelSize, mass / 2.0f);
            wheel.Position = torso.Position + new Vector2(0, torsoSize.Y / 2.0f);
            wheel.Body.Friction = 0.8f;

            // Create a joint to keep the torso upright
            //JointFactory.CreateFixedAngleJoint(world, torso.Body);
            torso.Body.FixedRotation = true;
            //JointFactory.CreateAngleJoint(world, torso.Body, wheel.Body);


            // Connect the feet to the torso
            axis = JointFactory.CreateRevoluteJoint(world, torso.Body, wheel.Body, Vector2.Zero);
            axis.CollideConnected = false;
            //JointFactory.CreateFixedMouseJoint(world, torso.Body, Vector2.Zero);


            axis.MotorEnabled = true;
            axis.MotorSpeed = 0;
            axis.MaxMotorTorque = 3;
            axis.MaxMotorTorque = 10;

            previousJump = DateTime.Now;
        }

        public void Move(Movement movement)
        {
            switch (movement)
            {
                case Movement.Left:
                    axis.MotorSpeed = -MathHelper.TwoPi * speed;
                    sprite.LoopAnimation("Walk");
                    sprite.reverse = true;
                    break;

                case Movement.Right:
                    axis.MotorSpeed = MathHelper.TwoPi * speed;
                    sprite.LoopAnimation("Walk");
                    sprite.reverse = false;
                    break;

                case Movement.Stop:
                    axis.MotorSpeed = 0;
                    sprite.LoopAnimation("Idle");
                    break;
            }
        }


        public void Jump()
        {
            if ((DateTime.Now - previousJump).TotalSeconds >= jumpInterval)
            {
                torso.Body.ApplyLinearImpulse(ref jumpForce);
                previousJump = DateTime.Now;
                sprite.LoopAnimation("Jump");
            }
        }


        public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            Rectangle destination = new Rectangle((int)torso.Position.X, (int)torso.Position.Y, sprite.Width, sprite.Height);
            Vector2 origin = new Vector2(sprite.Width + sprite.Width / 2, sprite.Height + sprite.Height / 2);
            sprite.Draw(gameTime, spriteBatch, destination, origin, 0.0f, Color.White, 0.0f);
            //sprite.Draw(torso.Position, Vector2.Zero, gameTime, spriteBatch);
            //torso.Draw(spriteBatch, gameTime);
            //wheel.Draw(spriteBatch, gameTime);
        }

        public bool OnGround()
        {
            return !torso.Body.Awake;
        }
    }

    public enum Movement
    {
        Left,
        Right,
        Stop
    }
}
